package scaffold

import (
	_const "gitee.com/lstack_light/go-light/internal/pkg/global"
	templates2 "gitee.com/lstack_light/go-light/internal/scaffold/templates"
	"log"
	"os"
	"path/filepath"
	"strings"
)

/**
  @author: light
  @since: 2023/9/2
  @desc: 目标文件生成器
*/

func Generate(dir, project, fileName string) bool {
	split := strings.Split(dir, "\\")
	for split[len(split)-1] != project {
		split = split[:len(split)-1]
		if 0 == len(split) {
			log.Fatal("未找到当前项目：", project)
			return false
		}
	}
	// 生成依赖
	module, dependencyErr := generateDependency(split)
	if nil != dependencyErr {
		log.Fatal(dependencyErr)
		return false
	}
	// 定义并创建文件夹
	dirs := []string{
		strings.Join(split, "/") + "/config",
		strings.Join(split, "/") + "/init",
		strings.Join(split, "/") + "/deploy",
		strings.Join(split, "/") + "/cmd",
		strings.Join(split, "/") + "/internal/model/bto",
		strings.Join(split, "/") + "/internal/model/dto",
		strings.Join(split, "/") + "/internal/model/vto",
		strings.Join(split, "/") + "/internal/controller",
		strings.Join(split, "/") + "/internal/service/impl",
		strings.Join(split, "/") + "/internal/middleware",
		strings.Join(split, "/") + "/internal/tool",
		strings.Join(split, "/") + "/internal/pkg",
		strings.Join(split, "/") + "/pkg",
		strings.Join(split, "/") + "/third_party",
		strings.Join(split, "/") + "/test",
	}
	for _, catalog := range dirs {
		err := os.MkdirAll(catalog, os.ModePerm)
		if err != nil {
			log.Fatal(err)
			return false
		}
	}
	// 截取模块名称
	name := strings.ReplaceAll(strings.Title(fileName), " ", "")
	// 构造执行器
	invoker := &templates2.Invoker{}
	// 实体相关操作
	modelCommand := &templates2.Model{Receiver: &templates2.Receiver{}, TemplateParams: templates2.TemplateParams{
		OutputFile:   strings.Join(split, "/") + "/internal/model/bto/" + strings.ToLower(fileName) + ".go",
		TemplateName: strings.Join(split, "/") + "/internal/model/model.go.tmpl",
		Module:       module,
		Name:         name,
	}}
	// 业务层接口相关操作
	serviceCommand := &templates2.Service{Receiver: &templates2.Receiver{}, TemplateParams: templates2.TemplateParams{
		OutputFile:   strings.Join(split, "/") + "/internal/service/" + strings.ToLower(fileName) + ".go",
		TemplateName: strings.Join(split, "/") + "/internal/service/service_interface.go.tmpl",
		Module:       module,
		Name:         name,
	}}
	// 业务层实现相关操作
	serviceImplCommand := &templates2.ServiceImpl{Receiver: &templates2.Receiver{}, TemplateParams: templates2.TemplateParams{
		OutputFile:   strings.Join(split, "/") + "/internal/service/impl/" + strings.ToLower(fileName) + ".go",
		TemplateName: strings.Join(split, "/") + "/internal/service/impl/service_impl.go.tmpl",
		Module:       module,
		Name:         name,
	}}
	// 路由层相关操作
	routerCommand := &templates2.Router{Receiver: &templates2.Receiver{}, TemplateParams: templates2.TemplateParams{
		OutputFile:   strings.Join(split, "/") + "/internal/controller/" + strings.ToLower(fileName) + ".go",
		TemplateName: strings.Join(split, "/") + "/internal/controller/controller.go.tmpl",
		Module:       module,
		Name:         name,
	}}
	// 主函数相关操作
	mainCommand := &templates2.Main{Receiver: &templates2.Receiver{}, TemplateParams: templates2.TemplateParams{
		OutputFile:   strings.Join(split, "/") + "/cmd/main.go",
		TemplateName: strings.Join(split, "/") + "/cmd/main.go.tmpl",
		Module:       module,
		Name:         name,
	}}
	// 配置责任链
	routerCommand.Receiver.SetNext(mainCommand)
	serviceImplCommand.Receiver.SetNext(routerCommand)
	serviceCommand.Receiver.SetNext(serviceImplCommand)
	modelCommand.Receiver.SetNext(serviceCommand)
	// 设置执行器命令
	invoker.SetCommand(modelCommand)
	// 执行命令
	invoker.ExecuteCommand(_const.InitEvent)
	return true
}

func generateDependency(split []string) (string, error) {
	// 查找 go mod 中的 module
	module := ""
	mod := filepath.Join(strings.Join(split, "/"), "go.mod")
	content, readErr := os.ReadFile(mod)
	if readErr != nil {
		log.Fatal("读取 go mod 文件失败：", readErr)
		return module, readErr
	}
	// 解析依赖
	lines := strings.Split(string(content), "\n")
	for _, line := range lines {
		if strings.HasPrefix(line, "module") {
			module = strings.TrimSpace(strings.ReplaceAll(line, "module", ""))
			break
		}
	}
	return module, nil
}
